use std::ffi::{CStr, c_char, c_void};
use std::slice;

use crate::cp437::cp437_byte_to_utf8_char;

unsafe extern "C" {
  fn strings_c_str(ptr: *const c_void) -> *const u8;
  fn strings_size(ptr: *const c_void) -> usize;
}

pub fn cxx_string_as_bytes(ptr: *const c_void) -> &'static [u8] {
  unsafe { slice::from_raw_parts(strings_c_str(ptr), strings_size(ptr)) }
}

pub fn cxx_string_to_string(ptr: *const c_void) -> String {
  let bytes = cxx_string_as_bytes(ptr);
  let bytes: Vec<u8> = bytes.into_iter().flat_map(|&byte| cp437_byte_to_utf8_char(byte).to_owned()).collect();
  unsafe { String::from_utf8_unchecked(bytes) }
}

pub fn c_string_as_bytes(ptr: *const c_char) -> &'static [u8] {
  unsafe { CStr::from_ptr(ptr).to_bytes() }
}

pub fn c_string_to_string(ptr: *const c_char) -> String {
  let bytes = c_string_as_bytes(ptr);
  let bytes: Vec<u8> = bytes.into_iter().flat_map(|&byte| cp437_byte_to_utf8_char(byte).to_owned()).collect();
  unsafe { String::from_utf8_unchecked(bytes) }
}
